<template>
  <ZForm
    :fields="reportFields"
    :initial-values="reportData"
    :schema="reportSchema"
    @submit="onSubmit"
  >
    <div class="flex gap-1 justify-end">
      <ZButton
        class="mt-2"
        color="secondary"
        icon-class="icon-[mdi--restart] size-6"
        type="reset"
      >
        重 置
      </ZButton>
      <ZButton
        class="mt-2"
        color="primary"
        icon-class="icon-[mdi--content-save] size-6"
        type="submit"
        :loading="isLoading"
      >
        保 存
      </ZButton>
    </div>
  </ZForm>
</template>

<script setup lang="ts">
import { ref, watch } from "vue";
import type { SubmissionContext } from "vee-validate";
import { z } from "zod";
import { formatDate } from "@vueuse/core";

import type { FormFields } from "@/components/form/types";
import ZForm from "@/components/form/ZForm.vue";
import ZButton from "@/components/ui/ZButton.vue";

import type { Report } from "@/stores";
import { useMutation, useQueryCache } from "@pinia/colada";
import { REPORT_QUERY_KEYS } from "@/query/report";
import {
  createReport,
  updateReport,
  type CreateReportData,
} from "@/apis/report";
import type { ApiResponse } from "@/apis";

const props = defineProps<{
  courseId: number;
  initValues?: Report;
  serial?: number;
}>();

const emit = defineEmits<{
  success: [Report];
}>();

const reportSchema = z.object({
  serial: z
    .number()
    .min(1, "序号最小值为1")
    .max(12, "序号最大值为8")
    .int()
    .positive("序号必须为正整数"),
  name: z.string().max(64, "报告名称最多64个字符"),
  objectives: z.string().min(1, "目的与要求不能为空"),
  equipment: z.string().min(1, "仪器设备不能为空"),
  content: z.string().min(1, "内容不能为空"),
  result: z.string().min(1, "实验结果不能为空"),
  date: z.coerce
    .date({ message: "不是有效的日期" })
    .transform((date) => formatDate(date, "YYYY-MM-DD")),
});

const reportFields: FormFields = [
  [
    {
      name: "serial",
      label: "报告序号",
      type: "number",
      inputAttributes: {
        placeholder: "请输入报告序号",
      },
    },
    {
      name: "date",
      label: "实验日期",
      type: "calendar-dropdown",
    },
  ],
  {
    name: "name",
    label: "报告名称",
    type: "text",
    inputAttributes: {
      placeholder: "请输入报告名称",
    },
  },
  {
    name: "objectives",
    label: "目的与要求",
    type: "markdown",
    inputAttributes: {
      placeholder: "请输入实验目的与要求",
      rows: 3,
    },
  },
  {
    name: "equipment",
    label: "仪器设备",
    type: "markdown",
    inputAttributes: {
      placeholder: "请输入使用的仪器设备",
      rows: 3,
    },
  },
  {
    name: "content",
    label: "实验内容",
    type: "markdown",
    inputAttributes: {
      placeholder: "请详细描述实验内容和步骤",
    },
  },
  {
    name: "result",
    label: "实验结果",
    type: "markdown",
    inputAttributes: {
      placeholder: "请输入实验结果和分析",
    },
  },
];
const now = new Date();
const initValues = {
  name: "",
  objectives: "",
  equipment: "",
  content: "",
  result: "",
  date: formatDate(now, "YYYY-MM-DD"),
};
const reportData = ref<Partial<Report>>();

watch(
  [() => props.initValues, () => props.serial],
  ([value, serial]) => {
    if (value) {
      reportData.value = value;
    } else {
      reportData.value = {
        ...initValues,
        serial,
      };
    }
  },
  {
    immediate: true,
  }
);

// 数据集不分页
const queryCache = useQueryCache();

const { isLoading, mutateAsync } = useMutation({
  mutation: (data: CreateReportData) =>
    props.initValues?.id
      ? updateReport(props.initValues.id, data)
      : createReport(data),

  onSuccess: (data) => {
    const oldData = queryCache.getQueryData<ApiResponse<Report>>(
      REPORT_QUERY_KEYS.list(props.courseId)
    );
    if (oldData) {
      queryCache.setQueryData(REPORT_QUERY_KEYS.list(props.courseId), {
        ...oldData,
        query: {
          ...oldData.query,
          results: props.initValues?.id
            ? oldData.query.results.map((i) =>
                i.id === props.initValues!.id ? { ...i, ...data.object } : i
              )
            : [...oldData.query.results, data.object],
        },
      });
    }
  },
});

async function onSubmit(
  values: z.infer<typeof reportSchema>,
  { resetForm, setErrors }: SubmissionContext
) {
  // 发起请求
  const data = await mutateAsync({ ...values, courseId: props.courseId });

  if (data?.success) {
    // 重置表单
    if (!props.initValues) resetForm();
    emit("success", data.object);
  } else {
    // 设置错误信息
    if (data?.errors) setErrors(data.errors);
  }
}
</script>
